import { Inject, Injectable, Logger } from '@nestjs/common';
import { DataSource } from 'typeorm';
import * as path from 'path';
import * as fs from 'fs';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

// 配置路径
const CONFIG_PATH = path.resolve(process.cwd(), 'billing', 'config.json');

@Injectable()
export class BillingService {
  private readonly logger = new Logger(BillingService.name);
  private config: any[];
  private billingName: string;
  constructor(
    @Inject(CACHE_MANAGER)
    private cacheManager: Cache,
    private readonly dataSource: DataSource,
  ) {
    // 计费规则读取
    this.loadConfig();
    this.watchConfigFile();
  }

  private loadConfig() {
    const configData = fs.readFileSync(CONFIG_PATH, 'utf-8');
    this.config = JSON.parse(configData);
  }

  getConfig() {
    return this.config;
  }

  /**
   * 监听文件变化重载
   * @private
   */
  private watchConfigFile() {
    fs.watchFile(CONFIG_PATH, () => {
      this.logger.log('Billing config file updated, reloading...');
      this.loadConfig();
    });
  }

  getBillingRules(typeName: string) {
    const type = this.config.find((t) => t.name === typeName);
    return type ? type.rules : null;
  }

  getBillingMethods(typeName: string, ruleName: string) {
    const type = this.config.find((t) => t.name === typeName);
    if (!type) return null;
    this.logger.debug('billing type: ' + type.description);
    const rule = type.rules.find((r) => r.name === ruleName);
    this.logger.debug('billing rule: ' + rule.description);
    // 设置消费名称
    this.billingName = `${type.description}-${rule.description}`;
    this.logger.debug('billing name: ' + this.billingName);
    return rule ? rule.methods : null;
  }

  /**
   * 计费
   */
  async triggerBilling(
    typeName: string,
    ruleName: string,
    methodName: string,
    callback: ({}: { fee: number; billingName: string }) => void,
  ) {
    const methods = this.getBillingMethods(typeName, ruleName);
    if (!methods) {
      throw new Error('Invalid type or rule name');
    }

    const method = methods.find((m) => m.name === methodName.toLowerCase());
    if (!method) {
      throw new Error('Invalid billing method');
    }
    // 补充name
    this.billingName += `（${method.description}）`;
    const fee = this.calculateFee(method.config);
    // Trigger the fee deduction logic (e.g., update user balance)
    this.logger.debug('deductFee: ' + fee);

    if (callback) return callback({ fee, billingName: this.billingName });

    return {
      fee,
      billingName: this.billingName,
      message: 'Billing successfully triggered',
    };
  }

  /**
   * 消费计算
   * @param config
   * @private
   */
  private calculateFee(config: any): number {
    return config.price;
  }
}
